package cn.dubito.manager.service;

import cn.dubito.entity.Product;
import cn.dubito.entity.enums.ProductStatusEnum;
import cn.dubito.manager.error.ErrorEnum;
import cn.dubito.manager.repository.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.persistence.criteria.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author liliang
 * @description: 产品接口
 * @date 2018/5/24.
 */
@Service
public class ProductService {

    private static Logger LOG = LoggerFactory.getLogger(ProductService.class);

    @Autowired
    private ProductRepository repository;

    /**
     * 添加产品
     *
     * @param product
     * @return
     */
    public Product addProduct(Product product) {
        LOG.debug("创建产品参数: {}", product);
        // 数据校验
        checkProduct(product);
        // 设置默认值
        setDefault(product);
        Product result = repository.save(product);
        LOG.debug("创建产品,返回结果: {}", result);
        return result;
    }

    /**
     * 查询单个产品
     *
     * @param id id
     * @return 产品
     */
    public Product findProduct(String id) {
        Assert.notNull(id, "产品编号不能为空");
        LOG.debug("查询单个产品,id={}", id);

        Product product = repository.findOne(id);
        LOG.debug("查询单个产品,返回结果:{}", product);
        return product;
    }

    /**
     * 分页查询
     *
     * @param idList id列表
     * @param minRewardRate 收益范围小
     * @param maxRewardRate 收益范围大
     * @param statusList 状态列表
     * @param pageable 分页查询
     * @return 分页对象
     */
    public Page<Product> query(List<String> idList,
                               BigDecimal minRewardRate,
                               BigDecimal maxRewardRate,
                               List<String> statusList,
                               Pageable pageable) {

        LOG.debug("查询产品,idList={},minRewardRate={},maxRewardRate={},statusList={},pageable={}",
                idList,minRewardRate,maxRewardRate,statusList,pageable);
        Specification<Product> specification = new Specification<Product>() {
            @Override
            public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Expression<String> idCol = root.get("id");
                Expression<BigDecimal> rewardRateCol = root.get("rewardRate");
                Expression<String> statusCol = root.get("status");

                List<Predicate> predicates = new ArrayList<>();
                if (idList != null && idList.size() > 0) {
                    predicates.add(idCol.in(idList));
                }
                if (minRewardRate != null) {
                    if (BigDecimal.ZERO.compareTo(minRewardRate) < 0) {
                        predicates.add(cb.ge(rewardRateCol,minRewardRate));
                    }
                }

                if (maxRewardRate != null) {
                    if (BigDecimal.ZERO.compareTo(maxRewardRate) < 0) {
                        predicates.add(cb.le(rewardRateCol,maxRewardRate));
                    }
                }

                if (statusList != null && statusList.size() > 0) {
                    predicates.add(statusCol.in(statusList));
                }
                query.where(predicates.toArray(new Predicate[0]));
                return null;
            }
        };

        Page<Product> page = repository.findAll(specification, pageable);
        LOG.debug("查询结果: page={}",page);
        return page;
    }

    /**
     * 设置默认值
     * 创建时间,更新时间
     * 投资步长,锁定期,状态
     *
     * @param product 产品
     */
    private void setDefault(Product product) {
        if (product.getCreateAt() == null) {
            product.setCreateAt(new Date());
        }
        if (product.getUpdateAt() == null) {
            product.setUpdateAt(new Date());
        }
        if (product.getStepAmount() == null) {
            product.setStepAmount(BigDecimal.ZERO);
        }
        if (product.getLockTerm() == null) {
            product.setLockTerm(0);
        }
        if (product.getStatus() == null) {
            product.setStatus(ProductStatusEnum.AUDITING.name());
        }
    }

    /**
     * 产品数据校验
     * 1,非空校验
     * 2,收益率 0~30
     * 3,投资步长需要是整数
     *
     * @param product 产品
     */
    private void checkProduct(Product product) {
        // 其他非空校验
        Assert.notNull(product, "产品参数不可以为空");
        Assert.notNull(product.getId(), ErrorEnum.ID_NOT_NULL.getCode());
        Assert.isTrue(BigDecimal.ZERO.compareTo(product.getRewardRate()) < 0 &&
                BigDecimal.valueOf(30).compareTo(product.getRewardRate()) >= 0, "收益率范围错误");
        Assert.isTrue(BigDecimal.valueOf(product.getStepAmount()
                .longValue()).compareTo(product.getStepAmount()) == 0, "投资步长需要是整数");
    }

    public static void main(String[] args) {
        System.out.println(BigDecimal.ZERO.compareTo(new BigDecimal(3)));
    }
}
